package jmotioncapture.testing.framework;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.BevelBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.awt.event.*;
import javax.swing.ButtonGroup;

import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import jmotioncapture.calculation.GeomCalculation;
import jmotioncapture.camera.FrameSet;
import jmotioncapture.geometry2D.Point;
import jmotioncapture.testing.framework.frameCalculation.FrameCalculationTestingPanel;
import jmotioncapture.testing.framework.util.TwoFilterTable;

import java.util.Vector;
import javax.swing.DefaultListModel;

/**
 * <i>Motion Capture Testing Framework.</i>
 * <p>
 * This framework is using for:
 * <p>
 * 1) Capturing different point for testing.
 * <p>
 * 2) Testing different algorithms in this API.
 * <p>
 * <p>
 * 
 * @author Kenneth Lo
 * 
 */
public class TestingPanel implements MouseMotionListener {

	/**
	 * GUI Variable
	 */
	protected JLabel dataLabel;

	/**
	 * GUI Variable
	 */
	private JTextField mutilPointTrackingNumTextField;

	/**
	 * GUI variable
	 */
	private ButtonGroup pointTrackingModeBtnGroup = new ButtonGroup();

	/**
	 * GUI variable
	 */
	private JRadioButton mutilPointTrackingRadioButton;

	/**
	 * GUI variable
	 */
	private JRadioButton singlePointTrackingRadioButton;

	/**
	 * GUI variable
	 */
	private JLabel numberOfPointLabel;

	/**
	 * GUI variable
	 */
	private JRadioButton captureDurationmsRadioButton;

	/**
	 * GUI variable
	 */
	private JRadioButton ofPointsRadioButton;

	/**
	 * GUI variable
	 */
	private ButtonGroup mouseMoveBtnGroup = new ButtonGroup();

	/**
	 * GUI Varibale
	 */
	private JTextField mouseMotionParaNoOfFrameTextField;



	/**
	 * GUI variable
	 */
	protected JCheckBox withLabelCheckBox;

	/**
	 * GUI variable
	 */
	protected JCheckBox withPointCheckBox;

	/**
	 * GUI variable
	 */
	protected JCheckBox withLinkedLineCheckBox;

	/**
	 * GUI variable
	 */
	private JScrollPane tableScrollPane;

	/**
	 * GUI variable
	 */
	private JTable table;

	/**
	 * GUI variable
	 */
	private TwoFilterTable tft;

	/**
	 * GUI variable
	 */
	private JTextField numberOfPointTextField;

	/**
	 * GUI variable
	 */
	protected DefaultListModel pointListModel;

	/**
	 * GUI variable
	 */
	private ButtonGroup btnGroup = new ButtonGroup();

	/**
	 * GUI variable
	 */
	private JRadioButton mouseClickRadioButton;

	/**
	 * GUI variable
	 */
	private JRadioButton mouseMotionRadioButton;

	/**
	 * GUI variable - the time between each point
	 */
	private JLabel timeBetweenEachPtLabel;

	/**
	 * GUI variable - FPS
	 */
	private JTextField fpsTextField;

	/**
	 * GUI variable - Point Capture Duration
	 */
	private JTextField captureDurationTextField;

	/**
	 * GUI variable - Displaying all the data to user
	 */
	protected JTextArea dataTextArea;

	/**
	 * GUI variable - Main frame
	 */
	protected JFrame frame;

	/**
	 * GUI variable - Displaying the real time coordinate
	 */
	protected JLabel coordinatesLabel;

	/**
	 * GUI variable - Main Panel
	 */
	protected JPanel panel;

	// *******************
	// * Other Variables *
	// *******************

	/**
	 * Execute the point capture thread
	 * {@link jmotioncapture.framework.PointCaptureTimer}
	 */
	private ExecutorService threadExecutor = Executors.newFixedThreadPool(2);

	/**
	 * Frame per second
	 */
	private int fps = 120;

	/**
	 * Store the collected points
	 */
	protected FrameSet frames = new FrameSet();

	/**
	 * Store the last collected points
	 */
	protected Point currentPoint = new Point((short) 0, (short) 0);

	/**
	 * thread status (Start / stop)
	 */
	protected boolean isCaptureStart = false;

	/**
	 * The duration of capturing points
	 */
	protected long captureTime;

	/**
	 * Time interval between each point (in ms)
	 */
	protected int interval = 1000 / fps;

	/**
	 * The duration of capturing points
	 */
	private int captureDuration;

	/**
	 * The number of point need to capture
	 */
	private int numberOfPoint;

	/**
	 * Value that decided how far (in piexl) should be counted as static point
	 */
	protected double staticPointTol = 5;

	// **********************************************************************************

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String args[]) {
		try {
			TestingPanel window = new TestingPanel();
			window.frame.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Create the application
	 */
	public TestingPanel() {

		// Setting window look and feel
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		// initialize the GUI
		initialize();

		// Update the fps and interval time
		fpsTextField_Changed();

		// Update GUI
		formEditableChecking();
	}

	/**
	 * Event handler for start button
	 * 
	 */
	private void startButton_Click() {

		// Clean past data
		dataTextArea.setText("");
		frames.clear();
		displayButton_Click(false);

		// Check for the input data
		try {
			this.fps = Integer.parseInt(fpsTextField.getText());
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, "Error: FPS", "Error: FPS ",
					JOptionPane.ERROR_MESSAGE);
			return;
		}

		// Type 1: Single Point + Mouse Motion + Period of Time
		if (singlePointTrackingRadioButton.isSelected()
				&& mouseMotionRadioButton.isSelected()
				&& captureDurationmsRadioButton.isSelected()) {

			try {
				this.captureDuration = Integer
						.parseInt(captureDurationTextField.getText());
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "Error: Capture Duration",
						"Error: Capture Duration ", JOptionPane.ERROR_MESSAGE);
				return;
			}

			// Finished checking
			// Start tracking
			PointCaptureTimer timer = new PointCaptureTimer(this,
					this.captureDuration, 1);
			this.threadExecutor.execute(timer);

		}

		// Type 3: Single Point + Mouse Motion + Number of point
		if (singlePointTrackingRadioButton.isSelected()
				&& mouseMotionRadioButton.isSelected()
				&& ofPointsRadioButton.isSelected()) {

			int temp = 0;
			try {
				temp = Integer.parseInt(mouseMotionParaNoOfFrameTextField
						.getText());
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null,
						"Error: Mouse Motion > # of points",
						"Error: Mouse Motion > # of points",
						JOptionPane.ERROR_MESSAGE);
				return;
			}

			// Finished checking
			// Start Tracking
			PointCaptureTimer timer = new PointCaptureTimer(this, temp, 3);
			this.threadExecutor.execute(timer);

		}

		// Type 2: Single Point + Mouse Click
		if (singlePointTrackingRadioButton.isSelected()
				&& mouseClickRadioButton.isSelected()) {
			try {
				this.numberOfPoint = Integer
						.parseInt(this.numberOfPointTextField.getText());
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "Error: Number of points",
						"Error: Number of points", JOptionPane.ERROR_MESSAGE);
				return;
			}

			// Finished checking
			PointCaptureTimer timer = new PointCaptureTimer(this,
					this.numberOfPoint, 2);
			this.threadExecutor.execute(timer);
		}

		// Type 4: Mutil Point + Mouse Motion + Number of Point
		if (mutilPointTrackingRadioButton.isSelected()
				&& mouseMotionRadioButton.isSelected()
				&& ofPointsRadioButton.isSelected()) {

			int typeValue = 0;
			int typeValue2 = 0;

			try {
				typeValue = Integer.parseInt(mouseMotionParaNoOfFrameTextField
						.getText());
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null,
						"Error: Mouse Motion > # of points",
						"Error: Mouse Motion > # of points",
						JOptionPane.ERROR_MESSAGE);
				return;
			}

			try {
				typeValue2 = Integer.parseInt(mutilPointTrackingNumTextField
						.getText());
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null,
						"Error: Mouse Motion > # of points",
						"Error: Mouse Motion > # of points",
						JOptionPane.ERROR_MESSAGE);
				return;
			}

			// Finished checking
			// Start Tracking
			PointCaptureTimer timer = new PointCaptureTimer(this, typeValue,
					typeValue2, 4);
			this.threadExecutor.execute(timer);

		}

		// Type 5: Mutil Point + Mouse Click
		if (mutilPointTrackingRadioButton.isSelected()
				&& mouseClickRadioButton.isSelected()) {

			int typeValue2 = 0;

			try {
				this.numberOfPoint = Integer
						.parseInt(this.numberOfPointTextField.getText());
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "Error: Number of points",
						"Error: Number of points", JOptionPane.ERROR_MESSAGE);
				return;
			}

			try {
				typeValue2 = Integer.parseInt(mutilPointTrackingNumTextField
						.getText());
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null,
						"Error: Mouse Motion > # of points",
						"Error: Mouse Motion > # of points",
						JOptionPane.ERROR_MESSAGE);
				return;
			}

			// Finished checking
			PointCaptureTimer timer = new PointCaptureTimer(this,
					this.numberOfPoint, typeValue2, 5);
			this.threadExecutor.execute(timer);
		}
	}

	/**
	 * Event handler for fpsTextField changed
	 * 
	 */
	private void fpsTextField_Changed() {

		try {
			this.interval = 1000 / Integer.parseInt(fpsTextField.getText());
			timeBetweenEachPtLabel.setText("Time between each point "
					+ this.interval + " ms");
		} catch (Exception e) {
			timeBetweenEachPtLabel.setText("Time between each point NA ms");
		}
	}

	/**
	 * Refresh all the data in the Table and repaint the GUI
	 */
	protected void refreshTable() {

		int size = frames.firstFrame().getNumberOfPoints();

		String[] columnNames = new String[size + 1];
		int[] columnWidth = new int[size + 1];
		int[] columnAlignment = new int[size + 1];
		Object[][] data = new Object[frames.size()][size + 1];

		columnNames[0] = "Frame";
		columnWidth[0] = 50;
		columnAlignment[0] = JLabel.CENTER;

		for (int i = 1; i <= size; i++) {
			columnNames[i] = "Point " + i;
			columnWidth[i] = 50;
			columnAlignment[i] = JLabel.CENTER;
		}

		for (int i = 0; i < data.length; i++) {

			data[i][0] = "Frame " + (i + 1);
			Vector<Point> pts = frames.frameAt(i).getPoints();
			for (int j = 1; j < data[i].length; j++) {
				data[i][j] = pts.elementAt(j - 1).toString();
			}
		}

		tft = new TwoFilterTable(columnNames, data, columnWidth,
				columnAlignment, 0, 1);
		table = tft.getTable();
		tableScrollPane.setViewportView(table);
		tableScrollPane.paintAll(tableScrollPane.getGraphics());
	}

	/**
	 * Event Handler
	 */
	protected void displayButton_Click(boolean isWait) {

		try {
			frame.remove(panel);
		} catch (RuntimeException e) {
			e.printStackTrace();
		}

		DrawTimer drawTimer = new DrawTimer(this, isWait);
		this.threadExecutor.execute(drawTimer);

	}

	public void mouseMoved(MouseEvent e) {

		if (this.mouseMotionRadioButton.isSelected()) {

			Point prevPt = this.currentPoint;
			this.currentPoint.setX((short) e.getX());
			this.currentPoint.setY((short) e.getY());
			this.currentPoint.setStaticCount(GeomCalculation.distance(prevPt,
					this.currentPoint));
			this.coordinatesLabel.setText(" (" + e.getX() + "," + e.getY()
					+ ")");
		}
	}

	public void mouseDragged(MouseEvent e) {

	}

	protected void panel_Click(MouseEvent e) {
		if (mouseClickRadioButton.isSelected()) {
			this.currentPoint.setX((short) e.getX());
			this.currentPoint.setY((short) e.getY());
			this.coordinatesLabel.setText(" (" + e.getX() + "," + e.getY()
					+ ")");

		}
	}

	private void configMenuItem_Click() {
		try {
			SettingPanel window = new SettingPanel();
			window.frame.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void formEditableChecking() {
		if (singlePointTrackingRadioButton.isSelected()) {
			mutilPointTrackingNumTextField.setEditable(false);
			captureDurationmsRadioButton.setEnabled(true);

			if (mouseMotionRadioButton.isSelected()) {
				numberOfPointTextField.setEditable(false);
				captureDurationmsRadioButton.setEnabled(true);
				ofPointsRadioButton.setEnabled(true);

				if (captureDurationmsRadioButton.isSelected()) {
					captureDurationTextField.setEditable(true);
					mouseMotionParaNoOfFrameTextField.setEditable(false);
				} else {
					captureDurationTextField.setEditable(false);
					mouseMotionParaNoOfFrameTextField.setEditable(true);
				}
			} else {
				captureDurationmsRadioButton.setEnabled(false);
				ofPointsRadioButton.setEnabled(false);
				numberOfPointTextField.setEditable(true);
				mouseMotionParaNoOfFrameTextField.setEditable(false);
				captureDurationTextField.setEditable(false);
			}
		} else {
			mutilPointTrackingNumTextField.setEditable(true);
			numberOfPointTextField.setEditable(false);
			captureDurationmsRadioButton.setEnabled(false);
			ofPointsRadioButton.setSelected(true);

			if (mouseMotionRadioButton.isSelected()) {

				captureDurationmsRadioButton.setEnabled(false);
				ofPointsRadioButton.setSelected(true);
				ofPointsRadioButton.setEnabled(true);

				if (captureDurationmsRadioButton.isSelected()) {
					captureDurationTextField.setEditable(true);
					mouseMotionParaNoOfFrameTextField.setEditable(false);
				} else {
					captureDurationTextField.setEditable(false);
					mouseMotionParaNoOfFrameTextField.setEditable(true);
				}
			} else {
				captureDurationmsRadioButton.setEnabled(false);
				ofPointsRadioButton.setEnabled(false);
				numberOfPointTextField.setEditable(true);
				mouseMotionParaNoOfFrameTextField.setEditable(false);
				captureDurationTextField.setEditable(false);
			}
		}
	}

	/**
	 * Initialize the contents of the frame
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setResizable(false);
		frame.setTitle("Motion Capture Testing Application");
		frame.getContentPane().setLayout(null);
		frame.setBounds(100, 100, 990, 786);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		coordinatesLabel = new JLabel();
		coordinatesLabel.setBounds(368, 10, 114, 14);
		frame.getContentPane().add(coordinatesLabel);

		panel = new JPanel();
		panel.addMouseListener(new MouseAdapter() {
			public void mouseClicked(final MouseEvent arg0) {
				panel_Click(arg0);
			}
		});
		panel.addMouseMotionListener(this);
		panel.setLayout(null);
		panel.setBorder(new TitledBorder(null, "",
				TitledBorder.DEFAULT_JUSTIFICATION,
				TitledBorder.DEFAULT_POSITION, null, null));
		panel.setBackground(Color.WHITE);
		panel.setBounds(10, 30, 472, 491);
		frame.getContentPane().add(panel);

		final JButton startButton = new JButton();
		startButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				startButton_Click();
			}
		});
		startButton.setText("Start");
		startButton.setBounds(770, 358, 200, 23);
		frame.getContentPane().add(startButton);

		final JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(488, 10, 278, 511);
		frame.getContentPane().add(scrollPane);

		dataTextArea = new JTextArea();
		scrollPane.setViewportView(dataTextArea);
		dataTextArea.setBorder(new BevelBorder(BevelBorder.LOWERED));

		pointListModel = new DefaultListModel();

		final JPanel mouseMotionPanel = new JPanel();
		mouseMotionPanel.setBorder(new LineBorder(Color.black, 1, false));
		mouseMotionPanel.setLayout(null);
		mouseMotionPanel.setBounds(770, 216, 200, 79);
		frame.getContentPane().add(mouseMotionPanel);

		final JLabel mouseMotionLabel = new JLabel();
		mouseMotionLabel.setFont(new Font("", Font.BOLD, 12));
		mouseMotionLabel.setText("Mouse Motion Parameter:");
		mouseMotionLabel.setBounds(7, 10, 179, 14);
		mouseMotionPanel.add(mouseMotionLabel);

		captureDurationTextField = new JTextField();
		captureDurationTextField.setBounds(150, 30, 47, 20);
		mouseMotionPanel.add(captureDurationTextField);
		captureDurationTextField.setText("2000");

		mouseMotionParaNoOfFrameTextField = new JTextField();
		mouseMotionParaNoOfFrameTextField.setText("150");
		mouseMotionParaNoOfFrameTextField.setEditable(false);
		mouseMotionParaNoOfFrameTextField.setBounds(150, 55, 47, 20);
		mouseMotionPanel.add(mouseMotionParaNoOfFrameTextField);

		captureDurationmsRadioButton = new JRadioButton();
		captureDurationmsRadioButton.setSelected(true);
		captureDurationmsRadioButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				captureDurationTextField.setEditable(true);
				mouseMotionParaNoOfFrameTextField.setEditable(false);
			}
		});
		mouseMoveBtnGroup.add(captureDurationmsRadioButton);
		captureDurationmsRadioButton.setText("Capture Duration (ms):");
		captureDurationmsRadioButton.setBounds(7, 30, 137, 23);
		mouseMotionPanel.add(captureDurationmsRadioButton);

		ofPointsRadioButton = new JRadioButton();
		ofPointsRadioButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				captureDurationTextField.setEditable(false);
				mouseMotionParaNoOfFrameTextField.setEditable(true);
			}
		});
		ofPointsRadioButton.setSelected(true);
		mouseMoveBtnGroup.add(ofPointsRadioButton);
		ofPointsRadioButton.setText("# of frames:");
		ofPointsRadioButton.setBounds(10, 50, 113, 23);
		mouseMotionPanel.add(ofPointsRadioButton);

		final JPanel mouseClickPanel = new JPanel();
		mouseClickPanel.setLayout(null);
		mouseClickPanel.setBorder(new LineBorder(Color.black, 1, false));
		mouseClickPanel.setBounds(770, 301, 200, 51);
		frame.getContentPane().add(mouseClickPanel);

		final JLabel mouseClickParameterLabel = new JLabel();
		mouseClickParameterLabel.setFont(new Font("", Font.BOLD, 12));
		mouseClickParameterLabel.setText("Mouse Click Parameter:");
		mouseClickParameterLabel.setBounds(10, 5, 180, 14);
		mouseClickPanel.add(mouseClickParameterLabel);

		numberOfPointLabel = new JLabel();
		numberOfPointLabel.setText("# of frames:");
		numberOfPointLabel.setBounds(10, 28, 124, 14);
		mouseClickPanel.add(numberOfPointLabel);

		numberOfPointTextField = new JTextField();
		numberOfPointTextField.setEditable(false);
		numberOfPointTextField.setText("1");
		numberOfPointTextField.setBounds(140, 25, 52, 20);
		mouseClickPanel.add(numberOfPointTextField);

		tableScrollPane = new JScrollPane();
		tableScrollPane.setBounds(10, 527, 954, 202);
		frame.getContentPane().add(tableScrollPane);

		table = new JTable();
		tableScrollPane.setViewportView(table);

		final JPanel displayPanel = new JPanel();
		displayPanel.setBorder(new LineBorder(Color.black, 1, false));
		displayPanel.setLayout(null);
		displayPanel.setBounds(772, 399, 200, 122);
		frame.getContentPane().add(displayPanel);

		final JButton displayButton = new JButton();
		displayButton.setBounds(123, 30, 67, 23);
		displayPanel.add(displayButton);
		displayButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				displayButton_Click(true);
			}

		});
		displayButton.setText("Display");

		final JLabel displayLabel = new JLabel();
		displayLabel.setFont(new Font("", Font.BOLD, 12));
		displayLabel.setText("Display Point on screen:");
		displayLabel.setBounds(10, 10, 180, 14);
		displayPanel.add(displayLabel);

		withLinkedLineCheckBox = new JCheckBox();
		withLinkedLineCheckBox.setText("With linked line");
		withLinkedLineCheckBox.setBounds(10, 51, 101, 23);
		displayPanel.add(withLinkedLineCheckBox);

		withPointCheckBox = new JCheckBox();
		withPointCheckBox.setSelected(true);
		withPointCheckBox.setText("With point");
		withPointCheckBox.setBounds(10, 30, 101, 23);
		displayPanel.add(withPointCheckBox);

		withLabelCheckBox = new JCheckBox();
		withLabelCheckBox.setText("With label");
		withLabelCheckBox.setBounds(10, 70, 101, 23);
		displayPanel.add(withLabelCheckBox);

		final JButton saveButton = new JButton();
		saveButton.setText("Save");
		saveButton.setBounds(123, 59, 67, 23);
		displayPanel.add(saveButton);

		final JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);

		final JMenu algorithmMenu = new JMenu();
		algorithmMenu.setText("Algorithm");
		menuBar.add(algorithmMenu);

		final JMenuItem lineMenuItem = new JMenuItem();
		lineMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				try {
					FrameCalculationTestingPanel window = new FrameCalculationTestingPanel(
							frames);
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		lineMenuItem.setText("Line");
		algorithmMenu.add(lineMenuItem);

		final JMenu menu = new JMenu();
		menu.setText("Setting");
		menuBar.add(menu);

		final JMenuItem configMenuItem = new JMenuItem();
		configMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {

				configMenuItem_Click();

			}
		});
		configMenuItem.setText("Config");
		menu.add(configMenuItem);

		final JPanel step2panel = new JPanel();
		step2panel.setBorder(new LineBorder(Color.black, 1, false));
		step2panel.setLayout(null);
		step2panel.setBounds(770, 113, 200, 79);
		frame.getContentPane().add(step2panel);

		mouseMotionRadioButton = new JRadioButton();
		mouseMotionRadioButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				formEditableChecking();
			}
		});
		mouseMotionRadioButton.setBounds(10, 10, 93, 23);
		step2panel.add(mouseMotionRadioButton);
		btnGroup.add(mouseMotionRadioButton);
		mouseMotionRadioButton.setText("Mouse Motion");

		final JLabel fpsLabel = new JLabel();
		fpsLabel.setBounds(10, 42, 36, 14);
		step2panel.add(fpsLabel);
		fpsLabel.setText("FPS:");

		fpsTextField = new JTextField();
		fpsTextField.setBounds(38, 39, 57, 20);
		step2panel.add(fpsTextField);
		fpsTextField.addKeyListener(new KeyAdapter() {
			public void keyPressed(final KeyEvent arg0) {
				fpsTextField_Changed();
			}

			public void keyReleased(final KeyEvent arg0) {
				fpsTextField_Changed();
			}

			public void keyTyped(final KeyEvent arg0) {
				fpsTextField_Changed();
			}
		});
		fpsTextField.setText("120");

		timeBetweenEachPtLabel = new JLabel();
		timeBetweenEachPtLabel.setBounds(10, 60, 180, 14);
		step2panel.add(timeBetweenEachPtLabel);
		timeBetweenEachPtLabel.setText("Time between each point 500 ms");

		mouseClickRadioButton = new JRadioButton();
		mouseClickRadioButton.setSelected(true);
		mouseClickRadioButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				formEditableChecking();
			}
		});
		mouseClickRadioButton.setBounds(99, 10, 93, 23);
		step2panel.add(mouseClickRadioButton);
		btnGroup.add(mouseClickRadioButton);
		mouseClickRadioButton.setText("Mouse Click");

		final JLabel step4Label = new JLabel();
		step4Label.setFont(new Font("", Font.BOLD | Font.ITALIC, 12));
		step4Label.setText("Step 4:");
		step4Label.setBounds(772, 383, 54, 14);
		frame.getContentPane().add(step4Label);

		final JLabel step3Label = new JLabel();
		step3Label.setFont(new Font("", Font.BOLD | Font.ITALIC, 12));
		step3Label.setText("Step 3:");
		step3Label.setBounds(770, 202, 54, 14);
		frame.getContentPane().add(step3Label);

		final JLabel step2Label = new JLabel();
		step2Label.setFont(new Font("", Font.BOLD | Font.ITALIC, 12));
		step2Label.setText("Step 2:");
		step2Label.setBounds(770, 93, 54, 14);
		frame.getContentPane().add(step2Label);

		final JPanel step1Panel = new JPanel();
		step1Panel.setLayout(null);
		step1Panel.setBorder(new LineBorder(Color.black, 1, false));
		step1Panel.setBounds(772, 25, 198, 62);
		frame.getContentPane().add(step1Panel);

		singlePointTrackingRadioButton = new JRadioButton();
		singlePointTrackingRadioButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				formEditableChecking();
			}
		});
		pointTrackingModeBtnGroup.add(singlePointTrackingRadioButton);
		singlePointTrackingRadioButton.setBounds(5, 5, 183, 23);
		singlePointTrackingRadioButton.setText("Single Point Tracking");
		step1Panel.add(singlePointTrackingRadioButton);

		mutilPointTrackingRadioButton = new JRadioButton();
		mutilPointTrackingRadioButton.setSelected(true);
		mutilPointTrackingRadioButton.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent arg0) {
				formEditableChecking();
			}
		});
		pointTrackingModeBtnGroup.add(mutilPointTrackingRadioButton);
		mutilPointTrackingRadioButton.setText("Mutil Point Tracking:  #= ");
		mutilPointTrackingRadioButton.setBounds(5, 29, 147, 23);
		step1Panel.add(mutilPointTrackingRadioButton);

		mutilPointTrackingNumTextField = new JTextField();
		mutilPointTrackingNumTextField.setText("4");
		mutilPointTrackingNumTextField.setBounds(158, 30, 30, 20);
		step1Panel.add(mutilPointTrackingNumTextField);

		final JLabel step1Label = new JLabel();
		step1Label.setFont(new Font("", Font.BOLD | Font.ITALIC, 12));
		step1Label.setText("Step 1:");
		step1Label.setBounds(770, 5, 54, 14);
		frame.getContentPane().add(step1Label);

		dataLabel = new JLabel();
		dataLabel.setText("Ready");
		dataLabel.setBounds(10, 10, 352, 14);
		frame.getContentPane().add(dataLabel);
	}
}
